home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 26
/
Cream of the Crop 26.iso
/
program
/
wdj0797.zip
/
TUFFS.ZIP
/
EXCEPT9.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1997-04-22
|
4KB
|
163 lines
// File: except9.cpp
// Description: Shows how to implement an exception-safe private
// heap manager under Win32.
//
// Notes: Relies on the STL, which means it will only compile under
// BC++5.0 and later.
//
#include <iostream.h>
#include <except.h>
#include <cstring.h>
#include <map.h>
using namespace std;
class TBuffer;
// Listing 6 Begin
class TPrivateHeap
{
public:
TPrivateHeap(size_t initialSize = 0x10000, DWORD flags = 0);
virtual ~TPrivateHeap();
virtual void* Allocate(size_t size, TBuffer* buffer);
virtual void Free(void* p);
virtual void Reset();
protected:
size_t OriginalSize;
HANDLE Handle;
DWORD Flags;
// Use STL map class to track allocations that have been made from
// this private heap so it can be restored in case of a failure.
// The map is indexed by the address of the block in the heap
// so it can be freed efficiently during normal operation, and its
// value is the size of the block for restoration purposes.
typedef map<void*, TBuffer*, less<void*> > HeapMap;
HeapMap Allocated;
};
// Listing 6 End
// Listing 7 Begin
class TBuffer
{
friend class TPrivateHeap;
public:
TBuffer(size_t size, TPrivateHeap &heap, char init = 0);
~TBuffer();
virtual operator char*();
protected:
TPrivateHeap &Heap;
size_t Size;
char Init;
void* Buffer;
};
// Listing 7 End
TPrivateHeap::TPrivateHeap(size_t initialSize, DWORD flags):
Flags(flags), OriginalSize(initialSize)
{
// Construct a Win32 private heap with the initial size as given.
Handle = HeapCreate(0, initialSize, 0);
}
TPrivateHeap::~TPrivateHeap()
{
HeapDestroy(Handle);
}
void* TPrivateHeap::Allocate(size_t size, TBuffer* buffer)
{
// Record the presence of the block.
void* result = HeapAlloc(Handle, Flags, size);
Allocated[result] = buffer;
return result;
}
void TPrivateHeap::Free(void* p)
{
HeapFree(Handle, Flags, p);
Allocated.erase(p);
}
// Listing 9 Begin
void TPrivateHeap::Reset()
{
// The heap is wrecked. Restore it.
HeapDestroy(Handle);
Handle = HeapCreate(Flags, OriginalSize, 0);
// Recreate all the objects that should be on the heap
// so that problems don't occur during subsequent access.
HeapMap::iterator i;
for (i = Allocated.begin(); i != Allocated.end(); i++)
{
cout << "Recreating block (" << (*i).second << ", " << (*i).second->Size << ")" << endl;
void* result = HeapAlloc(Handle, Flags, (*i).second->Size);
memset(result, (*i).second->Init, (*i).second->Size);
(*i).second->Buffer = result;
}
}
// Listing 9 End
TBuffer::TBuffer(size_t size, TPrivateHeap &heap, char init): Heap(heap), Size(size), Init(init)
{
Buffer = heap.Allocate(size, this);
memset(Buffer, init, size);
};
TBuffer::~TBuffer()
{
Heap.Free(Buffer);
}
TBuffer::operator char*()
{
return (char*)Buffer;
}
static TPrivateHeap heap;
void badFunction()
{
TBuffer p(10, heap);
cout << "Setting p to zero..." << endl;
memset(p, 0, -10);
}
int main()
{
// Listing 8 Begin
TBuffer b(20, heap);
for (int i=0; i<2; i++)
{
DWORD code = 0;
// Make sure that the "b" buffer is still functional.
memset(b, i, 20);
cout << "Before badFunction: b[0] == " << (int)b[0] << endl;
// Allocate a heap-based buffer object, just to make things
// more interesting (this one leaks, but can be re-created!
TBuffer* c = new TBuffer(30, heap);
try
{
try
{
cout << "Calling badFunction()" << endl;
badFunction();
delete c;
cout << "badFunction() completed without exception" << endl;
} catch (xmsg &x) {
cerr << "Exception caught '" << x.why() << "'" << endl;
} catch (...) {
cerr << "Unknown exception caught" << endl;
}
} __except (code=GetExceptionCode(), 1) {
cerr << "Unknown system exception " << hex << code << " caught" << endl;
heap.Reset();
}
cout << "After BadFunction: b[0] == " << (int)b[0] << endl;
}
// Listing 8 End
return 0;
}